#include <windows.h>

#include "lib.h"
#include "syncdlg.h"

SyncDialog::SyncDialog(HWND hParent, HINSTANCE hInst)
{
	this->hParent = hParent;
	this->hDialog = (HWND)0;
	this->hInst = hInst;
	result = -1;
}

SyncDialog::~SyncDialog()
{
	if (hDialog)
	{
		DestroyWindow(hDialog);
		hDialog = (HWND)0;
	}
}

int
SyncDialog::Run()
{
	DWORD waitResult;
	bool8 active = true;
	MSG msg;

	//
	// we use MsgWaitFor... without handles to allow Async Procedure Calls (APC)
	// to complete AND to handle window messages
	//

	if (!hDialog)
		return 0;

	if (!IsWindowVisible(hDialog))
		ShowWindow(hDialog, SW_SHOWNORMAL);

	while (active)
	{
		waitResult = MsgWaitForMultipleObjectsEx(0, (LPHANDLE)0, INFINITE,
			QS_ALLINPUT, MWMO_ALERTABLE);

		switch (waitResult)
		{
			default:
				active = false;
				break;

			case WAIT_IO_COMPLETION:	// APC was just called
				break;

			case WAIT_OBJECT_0:			// window msg
				while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
				{
					if (!IsDialogMessage(hDialog, &msg))
						if (msg.message != WM_QUIT)
						{
							TranslateMessage(&msg);
							DispatchMessage(&msg);
						}
						else
						{
							active = false;
							break;
						}
				}
				break;
		}
	}

	return result;
}

void
SyncDialog::EndDialog(HWND, int Result)
{
	result = Result;
	PostQuitMessage(0);
}

BOOL
SyncDialog::dialogProc(HWND /*hDlg*/, UINT Msg, WPARAM /*wParam*/,
	LPARAM /*lParam*/)
{
	switch (Msg)
	{
		case WM_DESTROY:
			SetWindowLong(hDialog, DWL_USER, (LONG)0);
			hDialog = (HWND)0;
			break;
	}

	return FALSE;
}

BOOL FAR PASCAL
SyncDialog::topDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	SyncDialog* This;

	if (Msg == WM_INITDIALOG)
	{
		RECT rc, rcDlg, rcParent;
		HWND hParent;

		SetWindowLong(hDlg, DWL_USER, (LONG)lParam);
		This = (SyncDialog*)lParam;
		This->hDialog = hDlg;

		// center Dialog within parent
		//
		hParent = GetParent(hDlg);
		if (hParent == (HWND)0)
			hParent = GetDesktopWindow();
		GetWindowRect(hParent, &rcParent);
		GetWindowRect(hDlg, &rcDlg);
		CopyRect(&rc, &rcParent);
		OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
		OffsetRect(&rc, -rc.left, -rc.top);
		OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
		SetWindowPos(hDlg, HWND_TOP,
			rcParent.left + (rc.right >> 1),
			rcParent.top + (rc.bottom >> 1),
			0, 0, SWP_NOSIZE);
	}
	else
		This = (SyncDialog*)GetWindowLong(hDlg, DWL_USER);

	if (This)
		return This->dialogProc(hDlg, Msg, wParam, lParam);
	else
		return FALSE;
}
